package io.github.jesse205.deskclock.lite;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.DisplayCutout;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Locale;

import io.github.jesse205.deskclock.lite.receivers.TimeUpdateReceiver;
import io.github.jesse205.deskclock.lite.utils.ActivityUtil;
import io.github.jesse205.deskclock.lite.utils.DimensionUtil;
import io.github.jesse205.deskclock.lite.utils.SharedPreferencesUtil;
import io.github.jesse205.deskclock.lite.utils.TimeUpdateTimer;
import io.github.jesse205.deskclock.lite.widgets.DynamicTextView;

public class MainActivity extends Activity {
    private final String TAG = "MainActivity";
    private final int IMMERSIVE_DURATION = 3000;

    private boolean lightTheme = false;
    private SharedPreferences sharedPreferences;
    private GestureDetector mGestureDetector;
    private Handler handler;
    private TimeUpdateTimer timeUpdateTimer;
    private TimeUpdateReceiver timeUpdateReceiver;
    private final ImmersiveSystemUIRunnable immersiveSystemUIRunnable = new ImmersiveSystemUIRunnable();

    private DateFormat timeFormat;
    private DynamicTextView timeTextView;
    private int screenWidthDp;
    private FrameLayout mainLayout;


    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 切换主题
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        lightTheme = sharedPreferences.getBoolean("light_theme", false);
        setTheme(lightTheme ? R.style.Theme_DeskClockLite_Light : R.style.Theme_DeskClockLite);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_FULLSCREEN);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            WindowManager.LayoutParams attributes = getWindow().getAttributes();
            attributes.layoutInDisplayCutoutMode = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
                    ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
                    : WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
            getWindow().setAttributes(attributes);
        }

        setContentView(R.layout.activity_main);
        mainLayout = findViewById(R.id.mainLayout);

        mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public void onLongPress(@NonNull MotionEvent e) {
                toggleTheme();
            }
        });
        mGestureDetector.setIsLongpressEnabled(true);
        mainLayout.setOnTouchListener((ev, ev2) -> mGestureDetector.onTouchEvent(ev2));

        timeTextView = findViewById(R.id.timeText);

        timeFormat = new SimpleDateFormat(getString(R.string.time_template), Locale.getDefault());
        handler = new Handler(getMainLooper());
        timeUpdateTimer = new TimeUpdateTimer(handler);
        timeUpdateTimer.setDuration(TimeUpdateTimer.DURATION_MINUTE);
        timeUpdateTimer.setOnTimeUpdateListener(this::updateTime);
        timeUpdateReceiver = new TimeUpdateReceiver(timeUpdateTimer, new DateFormat[]{timeFormat});

        refreshSize(getResources().getConfiguration());

        setupConfigureChangedListener();
        setupAvoidCutoutsListener();
        setupSystemUiVisibilityChangeListener();
        registerTimerUpdateReceiver();
    }


    @Override
    protected void onStop() {
        super.onStop();
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "onStop");
        }
        timeUpdateTimer.stop();
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "onStart");
        }
        timeUpdateTimer.start();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "onWindowFocusChanged: hasFocus=" + hasFocus);
        }
        handler.removeCallbacks(immersiveSystemUIRunnable);
        if (hasFocus) {
            immersiveSystemUILegacy();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "onResume");
        }
        immersiveSystemUILegacy();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterTimerUpdateReceiver();
    }

    private void setupConfigureChangedListener() {
        // BUG!: https://developer.android.google.cn/guide/topics/resources/runtime-changes?hl=zh-cn#allow-activity
        mainLayout.addView(new View(this) {
            @Override
            protected void onConfigurationChanged(Configuration newConfig) {
                super.onConfigurationChanged(newConfig);
                if (BuildConfig.DEBUG) {
                    Log.d(TAG, "mainLayout.onConfigurationChanged: newConfig=" + newConfig);
                }
                refreshSize(newConfig);
            }
        });
    }

    /**
     * 隐藏系统UI，需要在窗口变化到可见时调用。在安卓4.4及以下版本时不会隐藏导航栏，而是进入低调模式。
     */
    private void immersiveSystemUILegacy() {
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "hideSystemUI");
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            if (!hasWindowFocus()) {
                return;
            }
            int visibility = View.SYSTEM_UI_FLAG_LOW_PROFILE;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                visibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                visibility |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                        & ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
            }
            getWindow().getDecorView().setSystemUiVisibility(visibility);
        }
    }

    private void setupAvoidCutoutsListener() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            return;
        }
        mainLayout.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
            @NonNull
            @Override
            public WindowInsets onApplyWindowInsets(@NonNull View v, @NonNull WindowInsets insets) {
                DisplayCutout displayCutout = insets.getDisplayCutout();
                if (displayCutout != null) {
                    v.setPadding(
                            displayCutout.getSafeInsetLeft(),
                            displayCutout.getSafeInsetTop(),
                            displayCutout.getSafeInsetRight(),
                            displayCutout.getSafeInsetBottom()
                    );
                }
                return insets;
            }
        });

    }

    private void setupSystemUiVisibilityChangeListener() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB || Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            return;
        }
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> {
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onSystemUiVisibilityChange: visibility=" + visibility);
            }
            if (!hasWindowFocus()) {
                return;
            }
            // 如何当前拥有焦点，并且处于非低 Profile 模式，则延迟一段时间后进入沉浸式模式
            if ((visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) {
                handler.postDelayed(immersiveSystemUIRunnable, IMMERSIVE_DURATION);
            }
        });
    }

    private void updateTime(long time) {
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "updateTime: time=" + time);
        }
        String timeText = timeFormat.format(time);
        if (!timeTextView.getText().equals(timeText)) {
            timeTextView.setText(timeText);
        }
    }

    private void refreshSize(Configuration newConfig) {
        final int newScreenWidthDp;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
            newScreenWidthDp = newConfig.screenWidthDp;
        } else {
            newScreenWidthDp = DimensionUtil.px2dp(MainActivity.this, getWindowManager().getDefaultDisplay().getWidth());
        }
        refreshSize(newScreenWidthDp);
    }

    private void refreshSize(int newScreenWidthDp) {
        if (BuildConfig.DEBUG) {
            Log.d(TAG, "refreshSize: screenWidthDp=" + screenWidthDp);
        }
        if (newScreenWidthDp != screenWidthDp) {
            screenWidthDp = newScreenWidthDp;
            timeTextView.setTextSizeWidthFactor(getResources().getFraction(R.fraction.time_size_width_factor, 1, 1));
        }
    }

    private void toggleTheme() {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putBoolean("light_theme", !lightTheme);
        SharedPreferencesUtil.apply(editor);
        ActivityUtil.restartActivity(MainActivity.this);
    }

    private void registerTimerUpdateReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_TIME_CHANGED);
        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
        registerReceiver(timeUpdateReceiver, filter);
    }

    private void unregisterTimerUpdateReceiver() {
        unregisterReceiver(timeUpdateReceiver);
    }

    private final class ImmersiveSystemUIRunnable implements Runnable {
        @Override
        public void run() {
            immersiveSystemUILegacy();
        }
    }
}